use crate::tool::Tool;
use serde::Deserialize;
use tool_macro::tool;
use serde_json::{json, Value};
use anyhow::{Context, Result};
use async_trait::async_trait;

use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};

#[derive(Deserialize, Debug)]
struct SmtpConfig {
    server: String,
    username: String,
    password: String,
}

#[tool(
    struct_name = EmailSender,
    name = "send_email",
    description = "Send an email to a recipient.",
    args = [
        "to" : {
            "type": "string",
            "description": "The email address of the recipient.",
        },
        "subject" : {
            "type": "string",
            "description": "The subject of the email.",
        },
        "body" : {
            "type": "string",
            "description": "The body content of the email.",
        }
    ]
)]
fn send_email(to: &str, subject: &str, body: &str) -> Result<()> {
    let stmp_config: SmtpConfig  = {
        let content = std::fs::read_to_string("./config/smtp.toml").context("Read smtp config")?;
        toml::from_str(&content).context("Parse smtp config")?
    };
    
    let email = Message::builder()
        .from(format!("rManus Agent <{}>", stmp_config.username).parse().unwrap())
        .to(to.parse().unwrap())
        .subject(subject)
        .body(body.to_string())
        .context("Build email")?;

    let creds = Credentials::new(stmp_config.username, stmp_config.password);

    let mailer = SmtpTransport::relay(&stmp_config.server)
        .context("Communicate with SMTP")?
        .credentials(creds)
        .build();

    match mailer.send(&email) {
        Ok(_) => Ok(()),
        Err(e) => Err(e.into()),
    }
}

#[allow(unused)]
#[cfg(test)]
mod test {
    use super::*;

    #[tokio::test]
    async fn test_send() {
        let res = EmailSender::send_email(
            "1841818435@qq.com",
            "Hi",
            "HHHHHHHH"
        ).unwrap();
    }
}